package ma.view.gui;

import javax.swing.JComponent;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;

import ma.model.EBenchmarkInterface;

import java.awt.Component;
import java.util.List;
import java.util.NoSuchElementException;

/**
 * The class {@code CenterTabbedPane} creates a tabbed pane.
 * @author Oliver Eckstein
 *
 */
public class CenterTabbedPane
    extends JTabbedPane implements ObserverInterface {
    
    private static final long serialVersionUID = 1L;
    
    private List<EBenchmarkPanel> panels;
    private boolean oldErrorStatus = false;
    private EBenchmarkInterface eBenchmark;
    
    /**
     * The type of tabs that can be shown in this tool.
     * @author Oliver Eckstein
     *
     */
    public enum EBenchmarkTab { 
        CHOOSE_METHODS,
        SETUP_METHODS,
        PROCESS_PARAMETERS,
        GEOMETRY_PARAMETERS,
        SHOW_RESULT_OF_METHOD,
        SHOW_END_RESULTS
    }
    
    /**
     * To create a new instance of {@code ParameterTabbedPane}.
     * @param panels panels to be shown as a tabbed pane.
     */
    public CenterTabbedPane(List<EBenchmarkPanel> panels, EBenchmarkInterface eBenchmark) {
        this.panels = panels;
        this.eBenchmark = eBenchmark;        
        addTabs();
        update();
    }
    
    private void addTabs() {
    	JScrollPane pane;
        for(Component panel : panels) {
        	pane = new JScrollPane(panel);
        	pane.setName(panel.getName());
            this.add(pane, panels.indexOf(panel));
        }
    }
    
    /**
     * To deactivate all tabs of this class.    
     */
    public void deactivateTabs() {
        for(int i = 0; i < this.getTabCount(); i++) {
            this.setEnabledAt(i, false);
        }
    }
    
    /**
     * To activate all tabs of this class.    
     */
    public void activateTabs() {
        for(int i = 0; i < this.getTabCount(); i++) {
            this.setEnabledAt(i, true);
        }
    }
    
    /**
     * To get all tabs of this tabbed pane.
     * @return
     */
    public List<EBenchmarkPanel> getTabs() {
        return panels;
    }
    
    private int getScrollPaneIndex(EBenchmarkPanel panel) {
    	JScrollPane pane;
    	for (int i = 0; i < this.getComponentCount(); i++) {
    		pane = (JScrollPane) this.getComponent(i);
    		if (panel.equals((EBenchmarkPanel) pane.getViewport().getComponent(0))) {
    			return i;
    		}
    	}
    	throw new NoSuchElementException(panel + " not found in this JTabbedPane!");
    }


    @Override
    /*
     * (non-Javadoc)
     * @see ma.view.gui.ObserverInterface#update()
     */
    public void update() {
        
        if (eBenchmark.getSetCount() == 0) {
            panels.get(1).setActive(false);              
        } else {
            panels.get(1).setActive(true);  
        }
        
        /**
         * To deactivate all tabs caused by wrong input.
         */
        for(EBenchmarkPanel panel : panels) {
            if (panel.getErrorStatus()) {
                if(!oldErrorStatus) {
                deactivateTabs();
                oldErrorStatus = true;                
                }
                return;
            }            
        }
        
        /**
         * No wrong input, all tabs get activated.
         */
        activateTabs();
        oldErrorStatus = false;
        
        /**
         * To disable all tabs labeled as 'inactive'.
         */
        for(EBenchmarkPanel panel : panels) {
            if (!panel.isActive()) {
                this.setEnabledAt(getScrollPaneIndex(panel), false);
            }
        }
    }
    
    /**
     * To select a specific tab of this tabbed pane.
     * @param tab the tab to be selected.
     */
    public void showTab(EBenchmarkTab tab) {        
        for(EBenchmarkPanel comp : panels) {
            if((EBenchmarkTab) comp.getClientProperty("ident") == tab) {
                this.setSelectedIndex(getScrollPaneIndex(comp));            	
            }
        }
    }
    
    /**
     * To get the type of selected tab.
     * @return type of selected tab.
     */
    public EBenchmarkTab getSelectedTab() {        
        JScrollPane pane = (JScrollPane) this.getSelectedComponent();
        EBenchmarkPanel panel = (EBenchmarkPanel) pane.getViewport().getComponent(0);
        return (EBenchmarkTab) panel.getClientProperty("ident");
    }
    
    @Override
    public String toString() {
        return "JTabbedPane mit " + panels.size() + " Tabs";
    }
    
    /**
     * To add a component to this tabbed pane.
     * @param panel the panel to be added to the controller's view.
     * @param addAtIndex the index where to add the components.
     */
    public void addPanel(EBenchmarkPanel panel, int atIndex) {
        this.add(new JScrollPane(panel), atIndex);
        this.setTitleAt(atIndex, panel.getName());
        panels.add(panel);
    }
    
    /**
     * To add tabs to the controller's view.
     * @param components the components to be added to the controller's view.
     * @param addAtIndex the index where to add the components.
     */
    public void addPanels(List <EBenchmarkPanel> components, int addAtIndex) {
        for(int i = 0; i < components.size(); i++) {
            this.addPanel(components.get(i), i + addAtIndex);
        }
    }
    
    /**
     * To remove a component of this tabbed pane.
     * @param tab the tab to be removed.
     */
    public void remove(EBenchmarkTab tab) {
        for(JComponent comp : panels) {
            if((EBenchmarkTab) comp.getClientProperty("ident") == tab) {
                removeTab(comp);
                return;
            }            
        }        
    }
    
    /**
     * To remove a component of this tabbed pane.
     * @param comp the component to be removed.
     */
    public void removeTab(Component comp) {
        for (Component component : this.getComponents()) {
        	JScrollPane pane = (JScrollPane) component;
        	if(pane.getViewport().getComponent(0).equals(comp)) {
        		this.remove(pane);
        	}
        }    	
        panels.remove(comp);        
    }
    
    /**
     * To remove components of this tabbed pane.
     * @param components the components to be removed.
     */
    public void remove(List<EBenchmarkPanel> components) {
        for(Component comp : components) {
            removeTab(comp);
        }
    }
    
    /**
     * Finds out if tabbed pane contains the given tab.
     * @param tab the tab.
     * @return {@code true} if tabbed pane contains given tab.
     */
    public boolean hasTab(EBenchmarkTab tab) {
        for(JComponent comp : panels) {
            if((EBenchmarkTab) comp.getClientProperty("ident") == tab) {
                return true;
            }
        }
        return false;
    }
}
